package cn.lg.soar.gateway.handle;

import cn.lg.soar.common.data.msg.I18n;
import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.util.jackson.JacksonUtil;
import cn.lg.soar.core.handler.ex.ErrorResult;
import cn.lg.soar.core.handler.ex.SoarExceptionHandler;
import cn.lg.soar.gateway.util.RequestUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

/**
 * 使用 WebExceptionHandler 处理异常
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
//@Component // 暂不启用
@Order(-2)
public class CustomErrorWebExceptionHandler implements WebExceptionHandler {

    protected static final Logger LOGGER = LoggerFactory.getLogger(CustomErrorWebExceptionHandler.class);

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 设置响应json数据
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
        HttpResult<?> result;
        // 处理 404 异常
        if (HttpStatus.NOT_FOUND.equals(response.getStatusCode())) {
            result = HttpResult.fail("A0404", I18n.build("资源未找到"));
        } else {
            // 异常处理
            ErrorResult errorResult = SoarExceptionHandler.handle(ex, msg -> {
                LOGGER.warn("{} >>> {} >>> {}",
                        RequestUtils.getRemoteIp(request),
                        request.getURI().getPath(),
                        msg,
                        ex
                );
            });
            // 设置响应状态码
            response.setStatusCode(HttpStatus.valueOf(errorResult.getStatus()));
            result = errorResult.getResult();
        }
        String json = JacksonUtil.toJson(result);
        DataBuffer dataBuffer = response.bufferFactory().wrap(json.getBytes());
        // 改变请求响应返回行为
        return response.writeWith(Mono.just(dataBuffer));
    }
}